package dataCollection;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Vector;

public class AbstractDetailTreeAlgorithms {
  private AbstractDetailTreeAlgorithms() {}
  // TODO: Zeiger wiederherstellen

  public static void dumpTreeToDot(Tree<AbstractDetail> tree) {
    TreeElement<AbstractDetail> orig = goToTop(tree);
    try {
      FileWriter f = new FileWriter("out.dot");
      BufferedWriter bf = new BufferedWriter(f);
      bf.write("digraph AptitudesTree {\n");
      Iterator<TreeElement<AbstractDetail>> it = tree.top().iterator();
      while(it.hasNext()) {
        TreeElement<AbstractDetail> child = it.next();
        bf.write("root ->" + "\"" + child.getItem().getName() + "\";\n");
        dumpDotRecursively(child, bf);
      }      
      bf.write("}");
      bf.close();
      f.close();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } finally {
      tree.setTop(orig);
    }
  }
  
  public static Vector<Trait> getAllTraits(Tree<AbstractDetail> tree) {
    Vector<Trait> vec = new Vector<Trait>();
    TreeElement<AbstractDetail> orig = goToTop(tree);
    Iterator<TreeElement<AbstractDetail>> it = tree.top().iterator();
    while(it.hasNext()) {
      TreeElement<AbstractDetail> child = it.next();
      if(child.getItem() instanceof Trait) {
        vec.add((Trait)child.getItem());
      }
    }
    tree.setTop(orig);
    return vec;
  }

  public static Trait getTrait(Tree<AbstractDetail> tree, String trait_name) 
      throws InvalidDetailException {
    return (Trait)getTraitNode(tree, trait_name).getItem();
  }
  
  public static TreeElement<AbstractDetail> getTraitNode(Tree<AbstractDetail> tree, String trait_name) 
      throws InvalidDetailException {
    TreeElement<AbstractDetail> orig = goToTop(tree);
    Iterator<TreeElement<AbstractDetail>> it = tree.top().iterator();
    while(it.hasNext()) {
      TreeElement<AbstractDetail> child = it.next();
      if(child.getItem().getName().equals(trait_name) && child.getItem() instanceof Trait) {
        return child;
      }
    }
    throw new InvalidDetailException();
  } 
  
  public static AbstractDetail getDetail(Tree<AbstractDetail> tree, String name) 
      throws InvalidDetailException {
    return getDetailNode(tree, name).getItem();
  }
  
  public static TreeElement<AbstractDetail> getDetailNode(Tree<AbstractDetail> tree, String name) 
      throws InvalidDetailException {
    TreeElement<AbstractDetail> orig = goToTop(tree);
    Iterator<TreeElement<AbstractDetail>> it = tree.top().iterator();
    while(it.hasNext()) {
      TreeElement<AbstractDetail> child = it.next();
      System.out.println("CHILD:" + child.getItem().getName());
      if(child.getItem().getName().equals(name)) {
        tree.setTop(orig);
        return child;
      }
      else {
        TreeElement<AbstractDetail> elem = getDetailRecursively(child, name);
        if(elem == null) continue;
        tree.setTop(orig);
        return elem;
      }
    }
    throw new InvalidDetailException();
  }
  
  private static TreeElement<AbstractDetail> 
                 getDetailRecursively(TreeElement<AbstractDetail> elem, 
                                      String name) 
                                      throws InvalidDetailException {
    Iterator<TreeElement<AbstractDetail>> it = elem.iterator();
    while(it.hasNext()) {
      TreeElement<AbstractDetail> child = it.next();
      System.out.println("RECURSIVE: " + child.getItem().getName());
      if(child.getItem().getName().equals(name)) return child;
      else {
        TreeElement<AbstractDetail> node = getDetailRecursively(child, name);
        if(node != null) return node;
      }
    }
    return null;
  } 
  
  private static void dumpDotRecursively(TreeElement<AbstractDetail> elem, 
                                        BufferedWriter bf) throws IOException {
    Iterator<TreeElement<AbstractDetail>> it = elem.iterator();
    while(it.hasNext()) {
      TreeElement<AbstractDetail> child = it.next();
      bf.write("\"" +  elem.getItem().getName() + "\" -> \"" + child.getItem().getName() + "\";\n");
      dumpDotRecursively(child, bf);
    }
  } 
  
  /**
   * Traverse tree bottom up to the root node.
   * @returns: Previous top node of the tree
   */
  private static <ContentType> TreeElement<ContentType> 
                 goToTop(Tree<ContentType> tree) {
    TreeElement<ContentType> original = tree.top();
    while(tree.top().getParent() != null) {
      tree.pop();
    }
    return original;
  }
}
